This API is So Fetching

使用 Fetch

Fetch Living Standard

兼容性window.fetch polyfill

1. 概览

fetch(url/request[, options])
var request = new Request(url/request[, options]);

fetch 是全局量 window 的一个方法
request 是一个 Request 对象,Request 参数和 fetch 参数相同
options 是一个对象,主要key 如下:

1
2
3
4
5
6
7
8
9
10
11
method: GET/POST等
headers: 一个普通对象,或者一个 Headers 对象
body: 传递给服务器的数据,可以是字符串/Buffer/Blob/FormData,如果方法是 GET/HEAD,则不能有此参数
mode: cors / no-cors / same-origin, 是否跨域,默认是 no-cors
credentials: omit / same-origin / include
cache: default / no-store / reload / no-cache / force-cache / only-if-cached
redirect: follow / error / manual
referrer: no-referrer / client / 或者一个url
referrerPolicy: no-referrer / no-referrer-when-downgrade / origin / origin-when-cross-origin / unsafe-url
integrity: 资源完整性验证
fetch() 返回一个 promise,所以这么用

fetch API 使用 Promises 来处理结果/回调

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 对响应的简单处理
fetch('/some/url').then(function(response) {

}).catch(function(err) {
// 出错了;等价于 then 的第二个参数,但这样更直观 :(
});

// 链式处理,将异步变为类似单线程的写法: 高级用法.
fetch('/some/url').then(function(response) {
return //... 执行成功, 第1步...
}).then(function(returnedValue) {
// ... 执行成功, 第2步...
}).catch(function(err) {
// 中途任何地方出错...在此处理 :(
});

2. Headers

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 创建一个空的 Headers 对象,注意是Headers,不是Header
var headers = new Headers();

// 添加(append)请求头信息
headers.append('Content-Type', 'text/plain');
headers.append('X-My-Custom-Header', 'CustomValue');

// 判断(has), 获取(get), 以及修改(set)请求头的值
headers.has('Content-Type'); // true
headers.get('Content-Type'); // "text/plain"
headers.set('Content-Type', 'application/json');

// 删除某条请求头信息(a header)
headers.delete('X-My-Custom-Header');

// 创建对象时设置初始化信息
var headers = new Headers({
'Content-Type': 'text/plain',
'X-My-Custom-Header': 'CustomValue'
});

Headers对象方法:

1
2
3
4
5
6
7
8
9
append(key, value)
delete(key)
entries() 返回一个遍历器,类似二维数组,每一个 key 和它对应的 value 构成一个数组
get(key) 获取指定 key 的value,如果key被添加了多次,则返回第一次添加时的 value
getAll(key) 返回 key 对应的所有 value,组成一个数组
has(key)
keys() 所有 key 组成的遍历器
set(key, value) 更改 key 的值,如果 key 不存在,则相当于 append
values() 所有 value 组成的遍历器

1
2
3
4
5
6
7
8
//创建一个 Request 对象来包装请求头(Request Headers)
var request = new Request('/some-url', {
headers: new Headers({
'Content-Type': 'text/plain'
})
});

fetch(request).then(function() { /* handle response */ });

3. Request

Request接口

var request = new Request(url/request[, options]);

Request 对象表示一次 fetch 调用的请求信息。

属性(全部只读):

1
2
3
4
5
6
7
8
9
method - 支持 GET, POST, PUT, DELETE, HEAD
url - 请求的 URL
headers - 对应的 Headers 对象
referrer - 请求的 referrer 信息
mode - 可以设置 cors, no-cors, same-origin
credentials - 设置 cookies 是否随请求一起发送。可以设置: omit, same-origin
redirect - follow, error, manual
integrity - subresource 完整性值(integrity value)
cache - 设置 cache 模式 (default, reload, no-cache)

示例:

1
2
3
4
5
6
7
8
9
10
11
var request = new Request('/users.json', {
method: 'POST',
mode: 'cors',
redirect: 'follow',
headers: new Headers({
'Content-Type': 'text/plain'
})
});

// 使用!
fetch(request).then(function() { /* handle response */ });

在 Request 对象创建完成之后, 所有的属性都变为只读属性。一个 Request 就代表一串流(stream), 如果想要传递给另一个 fetch 方法,则需要进行克隆(clone 方法)。

4. Response

Response接口

var response = new Response([body][, init])

Response 代表响应, fetch 的 then 方法接收一个 Response 实例。

属性:

1
2
3
4
5
6
7
8
9
headers     //与响应相关联的 Headers 对象
ok //Boolean值,代表成功响应。status在 200 和 299 之间为 true
redirected //表示该Response是否来自一个重定向,如果是的话,它的URL列表将会有多个
status //状态码 (例如: 200, 404, 等等)
statusText //状态值(例如: OK)
type //类型 basic / cors / error / opaque
url //包含这个请求的URL
bodyUsed //存储一个Boolean判断主体是否已经被用于一个响应中
useFinalURL //Boolean 值, 代表 url 是否是最终 URL

方法:

1
2
3
4
5
6
7
8
clone() - 创建一个新的 Response 克隆对象.
error() - 返回一个新的,与网络错误相关的 Response 对象.
redirect() - 重定向,使用新的 URL 创建新的 response 对象..
arrayBuffer() - Returns a promise that resolves with an ArrayBuffer.
blob() - 返回一个 promise, resolves 是一个 Blob.
formData() - 返回一个 promise, resolves 是一个 FormData 对象.
json() - 返回一个 promise, resolves 是一个 JSON 对象.
text() - 返回一个 promise, resolves 是一个 USVString (text).

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
// 在 service worker 测试中手动创建 response
// new Response(BODY, OPTIONS)
var response = new Response('.....', {
ok: false,
status: 404,
url: '/'
});

// fetch 的 `then` 会传入一个 Response 对象
fetch('/')
.then(function(responseObj) {
console.log('status: ', responseObj.status);
});

5. 处理 JSON响应

封装了 JSON.parse(jsonString)

1
2
3
4
5
6
7
fetch('https://xxx.json').then(function(response) { 
// 转换为 JSON
return response.json();
}).then(function(j) {
// 现在, `j` 是一个 JavaScript object
console.log(j);
});

6. 处理 Text / HTML响应

1
2
3
4
5
6
7
fetch('/next/page')
.then(function(response) {
return response.text();
}).then(function(text) {
// <!DOCTYPE ....
console.log(text);
});

7. 处理Blob结果

Blob表示二进制原始数据,一个Blob对象就是一个包含有只读原始数据的类文件对象。

Blob
File API

创建blob

1. 通过构造函数

1
2
3
4
var blob = new Blob(dataArr:Array<any>, opt:{type:string});

//dataArray:数组,包含了要添加到Blob对象中的数据,数据可以是任意多个ArrayBuffer,ArrayBufferView, Blob,或者 DOMString对象。
//opt:对象,用于设置Blob对象的属性(如:MIME类型)

2. 通过Blob.slice()

1
2
3
4
5
Blob.slice(start:number, end:number, contentType:string)

\\start:开始索引,默认为0
\\end:截取结束索引(不包括end)
\\contentType:新Blob的MIME类型,默认为空字符串

3. 通过canvas.toBlob()

1
2
3
4
var canvas = document.getElementById("canvas");
canvas.toBlob(function(blob){
console.log(blob);
});

应用
https://www.cnblogs.com/hhhyaaon/p/5928152.html

  1. 通过Blob.slice方法,可以将大文件分片,轮循向后台提交各文件片段,即可实现文件的分片上传。
  2. window.URL对象可以为Blob对象生成一个网络地址,结合a标签的download属性,可以实现点击url下载文件。
  3. 把图片转化为Blob对象,生成URL(URL.createObjectURL(blob)),来显示图片。

通过 fetch 加载图像或者其他二进制数据

1
2
3
4
5
6
7
fetch('flowers.jpg')
.then(function(response) {
return response.blob();
})
.then(function(imageBlob) {
document.querySelector('img').src = URL.createObjectURL(imageBlob);
});

8. 提交表单数据(Posting Form Data)

1
2
3
4
5
6
7
8
9
10
11
12
13
fetch('/submit', {
method: 'post',
body: new FormData(document.getElementById('comment-form'))
});

//提交json数据
fetch('/submit-json', {
method: 'post',
body: JSON.stringify({
email: document.getElementById('email').value
answer: document.getElementById('answer').value
})
});

9. 跨域

https://www.zhihu.com/question/47029864/answer/150069385
如果服务器支持 CORS, 则在客户端设置相应的 Access-Control-Allow-Origin 即可得到数据。

1
2
3
4
5
6
7
8
9
10
11
let myHeaders = new Headers({
'Access-Control-Allow-Origin': '*',
'Content-Type': 'text/plain'
});
fetch(url, {
method: 'GET',
headers: myHeaders,
mode: 'cors'
}) .then((res) => {
// TODO
})

10. 在fetch中使用jsonp

JSONP only supports GET method, same as fetch-jsonp.

参考文章

https://segmentfault.com/a/1190000007455901
http://blog.csdn.net/renfufei/article/details/51494396
https://davidwalsh.name/fetch